1. Source Cross Validate Functions

source("./Mean Reversion/RMR.010 Cross Validate Functions.R")

2. Load Data

pricing_data <- read_csv("./Mean Reversion/Raw Data/pricing data.csv", col_types = c("iTdddddddci")) %>% 
  filter(date_time < "2017-10-09")

3. Parameter List

Description
A list of parameters passed to the functions below that describe the mean reversion pairs trading strategy.

Arguments
time_resolution: The number of seconds that each observation spans. Takes values 300, 900, 1800, 7200, 14400, and 86400.
quote_currency: A string indicating the quote currency of the currency pairs. Takes values “USDT” or “BTC”.
cointegration_test: A string indicating whether the Engle-Granger method or distance method is used to test for cointegration. Takes values “eg”, “tls”, or “distance”.
adf_threshold: The threshold for the ADF test statistic. Pairs below this threshold are selected when using the Engle-Granger method.
distance_threshold: The threshold for the rmse of the coins normalized prices. Pairs below this threshold are selected when using the distance method.
train_window: A lubridate period object representing the length of time the train set covers.
test_window: A lubridate period object representing the length of time the the test set covers.
model_type: A string indicating whether raw prices or log prices should be used. Takes value “raw” or “log”.
regression_type: A string indicating whether OLS, TLS, or a non-parametric regression should be used. Takes values “ols”, “tls”, or “non-parametric”.
spread_type: A string indicating whether the regression uses a rolling or fixed window. Takes value “rolling” or “fixed”.
rolling_window: The number of observations used in the lookback window of a rolling linear regression.
signal_logic: A string indicating which logic to use to generate signals. Takes values “scaled” or “discrete”.
signal_scaled_enter: The z-score threshold indicating the z-score that the signal is fully scaled in when the signal logic is scaled.
signal_discrete_enter: The z-score threshold for entering a position when the signal logic is discrete.
signal_discrete_exit: The z-score threshold for exiting a position when the signal logic is discrete.
signal_stop: A threshold for the spread z-score beyond which the strategy stops trading the coin pair.
signal_reenter: A boolean indicating whether the strategy should reenter positions after exceeding the signal_stop threshold once the spread z-score returns to a reasonable range.
signal_reenter_threshold: The z-score threshold for reentering a position if signal_reenter is TRUE. pair_allocation: A string indicating whether the capital allocation to the coin pairs should be equal or weighted. Takes values “equal”, “weighted”, and “scaled”.
pair_allocation_scaling: A double indicating the volatility scaling applied to the cointegration stat when the pair allocation is scaled. Higher numbers are associated with greater weight being placed on coin pairs with a high cointegration stat.

4. Set Parameters

params <- list(time_resolution = 300, 
               quote_currency = "USDT", 
               cointegration_test = "eg", 
               adf_threshold = -4.0, 
               distance_threshold = 0.00, 
               train_window = days(30), 
               test_window = days(20), 
               model_type = "raw", 
               regression_type = "ols", 
               spread_type = "rolling", 
               rolling_window = 1440, 
               signal_logic = "scaled", 
               signal_scaled_enter = 3.0, 
               signal_discrete_enter = 3.0, 
               signal_discrete_exit = 0.2, 
               signal_stop = 4.5, 
               signal_reenter = TRUE, 
               signal_reenter_threshold = 2.00, 
               pair_allocation = "equal", 
               pair_allocation_scaling = 1.00) 
number_pairs <- 8 

5. Cross Validation September 2017

plot_many(pricing_data = pricing_data,
          cutoff_date = "2017-09-01",
          params = params, 
          number_pairs = number_pairs)
## # A tibble: 3 x 3
##     coin_y   coin_x cointegration_stat
##      <chr>    <chr>              <dbl>
## 1 USDT_REP USDT_ZEC          -5.736107
## 2 USDT_ZEC USDT_REP          -5.501028
## 3 USDT_REP USDT_XMR          -4.170552

6. Cross Validation August 2017

plot_many(pricing_data = pricing_data,
          cutoff_date = "2017-08-01",
          params = params, 
          number_pairs = number_pairs)
## # A tibble: 10 x 3
##       coin_y    coin_x cointegration_stat
##        <chr>     <chr>              <dbl>
##  1  USDT_ETH  USDT_ZEC          -6.054465
##  2  USDT_ZEC  USDT_ETH          -5.967695
##  3  USDT_REP  USDT_ZEC          -5.783068
##  4  USDT_ZEC  USDT_REP          -5.717775
##  5 USDT_DASH  USDT_XMR          -5.299587
##  6  USDT_XMR USDT_DASH          -5.189520
##  7  USDT_ETH  USDT_REP          -4.730916
##  8  USDT_REP  USDT_ETH          -4.698637
##  9  USDT_LTC  USDT_ZEC          -4.412000
## 10  USDT_LTC  USDT_REP          -4.287901

7. Cross Validation July 2017

plot_many(pricing_data = pricing_data,
          cutoff_date = "2017-07-01",
          params = params, 
          number_pairs = number_pairs)
## # A tibble: 8 x 3
##      coin_y   coin_x cointegration_stat
##       <chr>    <chr>              <dbl>
## 1  USDT_REP USDT_XMR          -8.619821
## 2  USDT_XMR USDT_REP          -8.375164
## 3  USDT_REP USDT_BTC          -5.951596
## 4  USDT_BTC USDT_REP          -5.758097
## 5  USDT_BTC USDT_XMR          -5.631816
## 6  USDT_XMR USDT_BTC          -5.479049
## 7 USDT_DASH USDT_ZEC          -4.102562
## 8 USDT_DASH USDT_LTC          -4.007783

8. Cross Validation June 2017

plot_many(pricing_data = pricing_data,
          cutoff_date = "2017-06-01",
          params = params, 
          number_pairs = number_pairs)
## # A tibble: 18 x 3
##       coin_y    coin_x cointegration_stat
##        <chr>     <chr>              <dbl>
##  1  USDT_REP USDT_DASH          -8.229334
##  2 USDT_DASH  USDT_REP          -8.015776
##  3  USDT_REP  USDT_XMR          -6.997566
##  4  USDT_XMR  USDT_REP          -6.733495
##  5 USDT_DASH  USDT_XMR          -6.576085
##  6  USDT_XMR USDT_DASH          -6.568115
##  7  USDT_REP  USDT_ZEC          -6.472850
##  8 USDT_DASH  USDT_ZEC          -6.264925
##  9  USDT_ZEC USDT_DASH          -6.037114
## 10  USDT_ZEC  USDT_REP          -5.967876
## 11  USDT_XMR  USDT_ZEC          -5.616863
## 12  USDT_ZEC  USDT_XMR          -5.376518
## 13  USDT_ZEC  USDT_ETH          -4.849517
## 14  USDT_ETH  USDT_ZEC          -4.540834
## 15  USDT_XMR  USDT_BTC          -4.338487
## 16  USDT_BTC  USDT_XMR          -4.198414
## 17 USDT_DASH  USDT_ETH          -4.131498
## 18  USDT_REP  USDT_BTC          -4.047914

9. Cross Validation May 2017

plot_many(pricing_data = pricing_data,
          cutoff_date = "2017-05-01",
          params = params, 
          number_pairs = number_pairs)
## # A tibble: 15 x 3
##       coin_y    coin_x cointegration_stat
##        <chr>     <chr>              <dbl>
##  1 USDT_DASH  USDT_ZEC          -5.324670
##  2  USDT_ZEC USDT_DASH          -5.132194
##  3  USDT_XMR  USDT_ZEC          -5.068398
##  4  USDT_REP  USDT_ETH          -5.046993
##  5  USDT_ZEC  USDT_XMR          -4.672742
##  6 USDT_DASH  USDT_REP          -4.627560
##  7  USDT_XMR  USDT_ETH          -4.555376
##  8  USDT_ETH  USDT_REP          -4.527189
##  9  USDT_REP USDT_DASH          -4.506359
## 10 USDT_DASH  USDT_ETH          -4.416835
## 11  USDT_REP  USDT_ZEC          -4.386418
## 12  USDT_ZEC  USDT_REP          -4.285102
## 13  USDT_XMR USDT_DASH          -4.262944
## 14  USDT_ZEC  USDT_ETH          -4.088190
## 15 USDT_DASH  USDT_XMR          -4.036158

10. Cross Validation April 2017

plot_many(pricing_data = pricing_data,
          cutoff_date = "2017-04-01",
          params = params, 
          number_pairs = number_pairs)
## # A tibble: 7 x 3
##      coin_y    coin_x cointegration_stat
##       <chr>     <chr>              <dbl>
## 1  USDT_XMR USDT_DASH          -4.629148
## 2  USDT_ZEC  USDT_BTC          -4.568420
## 3  USDT_BTC  USDT_ZEC          -4.537424
## 4 USDT_DASH  USDT_XMR          -4.520526
## 5  USDT_XMR  USDT_ZEC          -4.418915
## 6  USDT_ZEC  USDT_XMR          -4.347171
## 7  USDT_REP  USDT_ETH          -4.156905

11. Cross Validation March 2017

plot_many(pricing_data = pricing_data,
          cutoff_date = "2017-03-01",
          params = params, 
          number_pairs = number_pairs)
## # A tibble: 10 x 3
##      coin_y    coin_x cointegration_stat
##       <chr>     <chr>              <dbl>
##  1 USDT_LTC  USDT_ZEC          -5.760345
##  2 USDT_LTC  USDT_REP          -4.973280
##  3 USDT_LTC  USDT_XMR          -4.944385
##  4 USDT_LTC  USDT_ETH          -4.838984
##  5 USDT_LTC USDT_DASH          -4.653697
##  6 USDT_LTC  USDT_BTC          -4.550198
##  7 USDT_XMR  USDT_LTC          -4.252412
##  8 USDT_XMR  USDT_BTC          -4.148961
##  9 USDT_ZEC  USDT_LTC          -4.007311
## 10 USDT_XMR USDT_DASH          -4.005995

12. Cross Validation February 2017

plot_many(pricing_data = pricing_data,
          cutoff_date = "2017-02-01",
          params = params, 
          number_pairs = number_pairs)
## # A tibble: 12 x 3
##      coin_y    coin_x cointegration_stat
##       <chr>     <chr>              <dbl>
##  1 USDT_REP  USDT_BTC          -5.161710
##  2 USDT_REP  USDT_ETH          -5.138239
##  3 USDT_REP  USDT_XMR          -5.002405
##  4 USDT_REP  USDT_ZEC          -4.994983
##  5 USDT_REP USDT_DASH          -4.777125
##  6 USDT_LTC  USDT_XMR          -4.582033
##  7 USDT_REP  USDT_LTC          -4.561970
##  8 USDT_ETH USDT_DASH          -4.357336
##  9 USDT_LTC  USDT_ZEC          -4.207423
## 10 USDT_XMR  USDT_LTC          -4.158443
## 11 USDT_ETH  USDT_REP          -4.146677
## 12 USDT_ZEC  USDT_LTC          -4.114974

13. Cross Validation January 2017

plot_many(pricing_data = pricing_data,
          cutoff_date = "2017-01-01",
          params = params, 
          number_pairs = number_pairs)
## # A tibble: 9 x 3
##     coin_y    coin_x cointegration_stat
##      <chr>     <chr>              <dbl>
## 1 USDT_REP  USDT_XMR          -6.684626
## 2 USDT_REP  USDT_ETH          -6.074812
## 3 USDT_REP  USDT_LTC          -5.994885
## 4 USDT_REP  USDT_BTC          -5.820387
## 5 USDT_REP  USDT_ZEC          -5.788823
## 6 USDT_REP USDT_DASH          -5.754398
## 7 USDT_LTC  USDT_BTC          -4.235045
## 8 USDT_ETH  USDT_REP          -4.225974
## 9 USDT_LTC  USDT_XMR          -4.003757

14. Cross Validation Full

results <- backtest_strategy_full(pricing_data = pricing_data, 
                                  params = params)  
## [1] "Cross validating strategy."
## [1] "Using train set from 2016-12-02 to 2017-01-01."
## [1] "Using test set from 2017-01-01 to 2017-01-21."
## [1] "Cross validating strategy."
## [1] "Using train set from 2016-12-22 to 2017-01-21."
## [1] "Using test set from 2017-01-21 to 2017-02-10."
## [1] "Cross validating strategy."
## [1] "Using train set from 2017-01-11 to 2017-02-10."
## [1] "Using test set from 2017-02-10 to 2017-03-02."
## [1] "Cross validating strategy."
## [1] "Using train set from 2017-01-31 to 2017-03-02."
## [1] "Using test set from 2017-03-02 to 2017-03-22."
## [1] "Cross validating strategy."
## [1] "Using train set from 2017-02-20 to 2017-03-22."
## [1] "Using test set from 2017-03-22 to 2017-04-11."
## [1] "Cross validating strategy."
## [1] "Using train set from 2017-03-12 to 2017-04-11."
## [1] "Using test set from 2017-04-11 to 2017-05-01."
## [1] "Cross validating strategy."
## [1] "Using train set from 2017-04-01 to 2017-05-01."
## [1] "Using test set from 2017-05-01 to 2017-05-21."
## [1] "Cross validating strategy."
## [1] "Using train set from 2017-04-21 to 2017-05-21."
## [1] "Using test set from 2017-05-21 to 2017-06-10."
## [1] "Cross validating strategy."
## [1] "Using train set from 2017-05-11 to 2017-06-10."
## [1] "Using test set from 2017-06-10 to 2017-06-30."
## [1] "Cross validating strategy."
## [1] "Using train set from 2017-05-31 to 2017-06-30."
## [1] "Using test set from 2017-06-30 to 2017-07-20."
## [1] "Cross validating strategy."
## [1] "Using train set from 2017-06-20 to 2017-07-20."
## [1] "Using test set from 2017-07-20 to 2017-08-09."
## [1] "Cross validating strategy."
## [1] "Using train set from 2017-07-10 to 2017-08-09."
## [1] "Using test set from 2017-08-09 to 2017-08-29."
## [1] "Cross validating strategy."
## [1] "Using train set from 2017-07-30 to 2017-08-29."
## [1] "Using test set from 2017-08-29 to 2017-09-18."
## [1] "Cross validating strategy."
## [1] "Using train set from 2017-08-19 to 2017-09-18."
## [1] "Using test set from 2017-09-18 to 2017-10-08."
ggplot(results, aes(x = date_time)) + 
  geom_line(aes(y = return_strategy_cumulative), colour = "blue", size = 1) + 
  geom_hline(yintercept = 1, colour = "black") + 
  labs(title = "Strategy Return vs Buy Hold Return", x = "Date", y = "Cumulative Return") 

print(results[["return_strategy_cumulative"]][nrow(results)]) 
## [1] 167.2748